﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VoliaStat.Properties;
using System.Threading;
using System.Diagnostics;



namespace VoliaStat
{



    public partial class MainForm : Form
    {

        const string STARS = "******";
        const string YES = "YES";
        const string NO = "NO";
        const int FETCHTIMER_INTERVAL = 1000;
        const long FETCHTICKS_INTERVAL_OK = 6000000000 ; // 600 sec
        const long FETCHTICKS_INTERVAL_ERROR = 6000000000 ; // 600 sec
        const long FETCHTICKS_INTERVAL_NOINET = 100000000 ; // 10 sec

        long _fetchticksinterval = FETCHTICKS_INTERVAL_OK;
        long _lastfetchticks=0;
        VoliaInfoClass _voliainfo = null;
        bool _isvoliaerror=false;

        Thread _thethread=null;

        long _trafficlimit=0;
        string _name,_pass;

        Icon _erricon=null;
        Icon _officon=null;

        Icon[] _persenticon;

        bool _isfetching=false;
        bool _isupdateneeded = false;
        long _lasttrafftotal=0;

        MyTaskbarNotifier NotifyWindow;

        IconAndNumber[] _icons = {  new IconAndNumber("00"),
                                    new IconAndNumber("07"),
                                    new IconAndNumber("12"),
                                    new IconAndNumber("18"),
                                    new IconAndNumber("25"),
                                    new IconAndNumber("32"),
                                    new IconAndNumber("36"),
                                    new IconAndNumber("43"),
                                    new IconAndNumber("50"),
                                    new IconAndNumber("57"),
                                    new IconAndNumber("62"),
                                    new IconAndNumber("69"),
                                    new IconAndNumber("75"),
                                    new IconAndNumber("82"),
                                    new IconAndNumber("87"),
                                    new IconAndNumber("93"),
                                    new IconAndNumber("99"),
                                    new IconAndNumber("100") };




        Icon FindClosestIcon(int persent)
        {
            Icon i=null;
            int delta = 101;
            int d;
            foreach (IconAndNumber n in _icons)
            {
                d = Math.Abs(persent-n.persent);
                if (d<=delta) 
                {
                    delta = d;
                    i = n.icon;
                }
            }
            if (i==null) i = _officon;
            return i;

        }



       void CreateInformer()
       {
            _voliainfo = null;
           
            try
            {

                string name = DESCryptClass.Decrypt(Settings.Default.UserName);
                string pass = DESCryptClass.Decrypt(Settings.Default.Password);
            
                _voliainfo = new VoliaInfoClass(name,pass);  

                if ((name.Length==0)||(pass.Length==0))
                {
                    this.Show();
                    this.WindowState = FormWindowState.Normal;
                    throw new Exception("Не указан номер договора или пароль.");
                }
            }
            catch(Exception error)
            {
                _voliainfo.SetError(error);

            }

        
            
       
       }



        void DoFetch()
        {

            if ((_voliainfo!=null)&&(!_voliainfo.IsError)) _voliainfo.Fetch();
          
            _isfetching = false;
            _isupdateneeded = true;

        }



        void ShowNotifyWindow()
        {


            NotifyWindow.Tuch();
        }


        void InfoWaitMode()
        {
            bUpdate.Enabled = false;
            TrayIcon.Icon = _officon;
            TrayIcon.Text = "Подождите...";
            lInfo.Text = "Подождите...";
            FetchTimer.Stop();
            _lastfetchticks =0;
            _isvoliaerror = false;
            FetchTimer_Update();


        }



        const long G1 = 1000000000;
        void InfoUpdate()
        {
            _isupdateneeded = false;
            _isvoliaerror = false;

            if (_voliainfo==null)
            {
                lInfo.Text = "Нет данных";
                TrayIcon.Text = "Нет данных";
                TrayIcon.Icon = _erricon;
                _isvoliaerror = true;

            } else
            {

                VoiaInfoParser p = new VoiaInfoParser(_voliainfo);

                if (p.IsError)
                {   _fetchticksinterval = p.IsNoInetError ? FETCHTICKS_INTERVAL_NOINET : FETCHTICKS_INTERVAL_ERROR;
                    lInfo.Text = p.Error;
                    TrayIcon.Icon = _erricon;
                    TrayIcon.Text = "Ошибка";
                    _isvoliaerror = true;
                    
                } else
                {   _fetchticksinterval = FETCHTICKS_INTERVAL_OK;
                    lInfo.Text = "Нет ошибок";
                    long total = p.TraffTotalInt;
                    if (_trafficlimit==0)
                    {
                        TrayIcon.Text=string.Format("{0:0,0.00}",(((float)total)/1000000));
                        TrayIcon.Icon =_persenticon[0];
                    } else
                    {
                        long persent  = total / (_trafficlimit*10000);
                        TrayIcon.Text=string.Format("{0:0,0.00} ({1}%)",(((float)total)/1000000),persent);
                        if (persent<0) persent=0;
                        if (persent>100) persent =100;
                        TrayIcon.Icon =_persenticon[(int)persent];
                    }


                    if ( (_lasttrafftotal/G1) != (total/G1) ) ShowNotifyWindow();
                    _lasttrafftotal = total;
                }


                int month_persent_for_today = DateTime.Now.Day*100 / DateTime.DaysInMonth(DateTime.Now.Year,DateTime.Now.Month );

                int persent_total, persent_today;
                if (_trafficlimit==0)
                {   persent_total  = 0;
                    persent_today  = 0;
                
                } else
                {   persent_total  = (int)((p.TraffTotalInt/10000) / _trafficlimit);
                    persent_today  = (int)((p.TraffTodayInt/10000) / _trafficlimit);
                }

                NotifyWindow.UpdateInfo(p,month_persent_for_today,persent_total,persent_today);
            }


            if (!_isfetching) 
            {   bUpdate.Enabled = true;
                UpdateTimer.Stop();
                FetchTimer.Interval = FETCHTIMER_INTERVAL;
                _lastfetchticks=DateTime.Now.Ticks;
                FetchTimer_Update();
                FetchTimer.Start();
            }


        }


        void Fetch()
        {
            if (_isfetching) return; 
            _isfetching = true;
            InfoWaitMode();
            
            if ((_voliainfo==null)||(_voliainfo.IsError)) CreateInformer();

			_thethread=new Thread(new ThreadStart(DoFetch));
			_thethread.Name="Fetch";

            _isupdateneeded = false;
            UpdateTimer.Start();
			_thethread.Start(); 
        
        }






        



        public MainForm()
        {
            InitializeComponent();

			NotifyWindow=new MyTaskbarNotifier();


			NotifyWindow.TitleClick+=new EventHandler(TitleClick);
			NotifyWindow.CloseClick+=new EventHandler(CloseClick);


			

        }

        void ShowSettingsWindow()
        {
           Show();
           WindowState = FormWindowState.Normal;
           Activate(); 
        }



        private void MainForm_Load(object sender, EventArgs e)
        {

            BeginInvoke(new MethodInvoker(delegate{   Hide();WindowState = FormWindowState.Minimized; }));

            _erricon = new Icon( this.GetType().Assembly.GetManifestResourceStream("VoliaStat.icons.voliaERR.ico"));
            _officon = new Icon( this.GetType().Assembly.GetManifestResourceStream("VoliaStat.icons.voliaOFF.ico"));

            _persenticon = new Icon[101];
            

            for (int i=0;i<101;i++)  _persenticon[i] = FindClosestIcon(i);

            _name = DESCryptClass.Decrypt(Settings.Default.UserName);
            _pass = DESCryptClass.Decrypt(Settings.Default.Password);
            if (_name.Length!=0) tbName.Text = _name;
            if (_pass.Length!=0) tbPass.Text = STARS ;

            if (Settings.Default.TrafficLimit.Length!=0)
            {   tbLimit.Text = Settings.Default.TrafficLimit;
                _trafficlimit = VoliaInfoClass.atoi(Settings.Default.TrafficLimit);
            }


            Fetch();


        }

        #region TRACKING MOUSE HOVER/LEAVE

        int MOUSETRACKINTERVAL = 300;
        long MOUSEOVERTICKS = 20000000;//2 sec
        long _mousehoverticks = 0;
        bool _mousetracking = false;
        Point _mousetrackposition ;


        void Mouse_Hover()
        {
            _mousetrackposition = MousePosition;

            if (_mousetracking) return;

            _mousetracking =true;

            _mousehoverticks = DateTime.Now.Ticks;
            MouseTimer.Interval = MOUSETRACKINTERVAL;
            MouseTimer.Start();

        }

        private void MouseTimer_Tick(object sender, EventArgs e)
        {
            if (MousePosition != _mousetrackposition) 
            {   MouseTimer.Stop();
                _mousetracking = false;
                NotifyWindow.KeepVisible = false;
                return;
            }
            if ((!NotifyWindow.KeepVisible) && (DateTime.Now.Ticks - _mousehoverticks > MOUSEOVERTICKS))
            {   ShowNotifyWindow();
                NotifyWindow.KeepVisible = true;
            }
        }




        #endregion



        #region MENUCLICKS



        private void TitleClick(object sender, EventArgs e)
        { 
            if (_isvoliaerror)  ShowSettingsWindow(); else  Fetch();
        }

        private void CloseClick(object sender, EventArgs e)
        {
            Close();
        }


        private void bSaveSettings_Click(object sender, EventArgs e)
        {
            Settings.Default.UserName = DESCryptClass.Encrypt(tbName.Text);
            
            if (tbPass.Text!=STARS)
            {
                Settings.Default.Password = DESCryptClass.Encrypt(tbPass.Text);
                tbPass.Text=STARS;
            }
            Settings.Default.TrafficLimit = tbLimit.Text;
            _trafficlimit = VoliaInfoClass.atoi(tbLimit.Text);


            Settings.Default.Save();
            CreateInformer();
            Fetch();
        }

        private void bAutostart_Click(object sender, EventArgs e)
        {
            int rc = ShortcutCreator.CreateInStartupFolder(Application.ExecutablePath,Application.StartupPath);
            switch (rc)
            {
                case ShortcutCreator.CREATED:
                    MessageBox.Show("Создан ярлык в папке автозагрузки."); 
                    break;
                case ShortcutCreator.DELETED:
                    MessageBox.Show("Ярлык из папки автозагрузки удален."); 
                    break;
                case ShortcutCreator.ERROR:
                    MessageBox.Show("Ошибка.");
                    break;
            
            }
        }

        private void bShow_Click(object sender, EventArgs e)
        {
            ShowNotifyWindow();
        }

        private void bUpdate_Click(object sender, EventArgs e)
        {
            Fetch();
        }



        private void Timer_Tick(object sender, EventArgs e)
        {
            if (_isupdateneeded) InfoUpdate();
        }

        private void bClose_Click(object sender, EventArgs e)
        {
            Close();
        }    
        
        
        
        private void bHide_Click(object sender, EventArgs e)
        {
             Hide();
        }       
        


        private void MainForm_Resize(object sender, EventArgs e)
        {
             if (WindowState == FormWindowState.Minimized)
             {
                Hide();
             }
        }




        private void TrayIcon_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)  ShowSettingsWindow();

            if (e.Button == MouseButtons.Left) ShowNotifyWindow();

            
        }

        private void TrayIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Fetch();
        }

        private void TrayIcon_MouseMove(object sender, MouseEventArgs e)
        {
            Mouse_Hover();  
        }


        private void FetchTimer_Update()
        {
            long delta = DateTime.Now.Ticks - _lastfetchticks;
            int p = (int)(((DateTime.Now.Ticks - _lastfetchticks)*100) / _fetchticksinterval);
            NotifyWindow.UpdateTimer(p>100 ? 100 : p);
        }

        private void FetchTimer_Tick(object sender, EventArgs e)
        {
            long delta = DateTime.Now.Ticks - _lastfetchticks;
            if (DateTime.Now.Ticks - _lastfetchticks > _fetchticksinterval) Fetch();
            FetchTimer_Update();

        }

        #endregion





    }       
        
        

}
